BEGIN_ADDRESS:
%include "Macro/protect.inc"
jmp	START
; [SECTION .gdt]
; GDT表
align 8
GDT:	   	
Descriptor		0,			0,	0	; 空描述符
DESC_CODE32:	Descriptor  BASE_CODE_ADD,	SegCode32Len - 1,	PT_CD_E+PT_S+PT_P_VALID+PT_D_32	; 非一致代码段
DESC_DATA32:	Descriptor	BASE_DATA_ADD, 	SegData32Len - 1,	PT_DA_RW+PT_S+PT_P_VALID+PT_D_32; 可读可写数据段
DESC_VIDEO:  	Descriptor 	0B8000h,      	0ffffh, 			PT_DA_RW+PT_S+PT_P_VALID	    ; 显存首地址
; GDT 结束

GdtLen		equ	$ - GDT		; GDT长度
GdtPtr		dw	GdtLen - 1	; GDT界限
			dd	0			; GDT基地址

; IDT表
align 8
IDT:
times	2	dw	0, 0, 0, 0
; IDT表 结束
IdtLen		equ	$ - IDT 	; IDT长度
IdtPtr		dw	IdtLen - 1	; IDT界限
			dd	0			; IDT基地址	

; GDT 选择子
SelectorCode32		equ	DESC_CODE32	- GDT
SelectorData32		equ	DESC_DATA32	- GDT
SelectorVideo		equ	DESC_VIDEO	- GDT

; 数据段
SEG_DATA32:
times	64	db	0
stack_prt:
	dd 	stack_prt
	dw 	0x10

Message		db	"Hello"
SegData32Len	equ	$ - SEG_DATA32

; 基地址
BASE_CODE_ADD	equ	SEG_CODE32 - BEGIN_ADDRESS + 0x10000
BASE_DATA_ADD	equ	SEG_DATA32 - BEGIN_ADDRESS + 0x10000
BASE_IDT_ADD	equ	TIMER_INT - BEGIN_ADDRESS + 0x10000

[BITS 16]
START:
	mov	ax, cs
	mov	ds, ax
	mov	es, ax
	mov	ss, ax
	mov	sp, 0100h
	
	; 为加载 GDTR 作准备
	xor	eax, eax
	mov	ax, ds
	shl	eax, 4
	add	eax, GDT		; eax <- gdt 基地址
	mov	dword [GdtPtr + 2], eax	; [GdtPtr + 2] <- gdt 基地址

	; 加载 GDTR
	lgdt	[GdtPtr]

	; 为加载 IDTR 作准备
	xor	eax, eax
	mov	ax, ds
	shl	eax, 4
	add	eax, IDT		
	mov	dword [IdtPtr + 2], eax

	; 加载 IDTR
	lidt	[IdtPtr]

	; 关中断
	cli

	; 打开地址线A20
	in	al, 92h
	or	al, 00000010b
	out	92h, al

	; 准备切换到保护模式
	mov	eax, cr0
	or	eax, 1
	mov	cr0, eax

	; 真正进入保护模式
	jmp	dword SelectorCode32:0	; 执行这一句会把 SelectorCode32 装入 cs,
					; 并跳转到 Code32Selector:0  处

; [SECTION .s32]; 32 位代码段. 由实模式跳入.
[BITS 32]

SEG_CODE32:
	
	; 测试lss用法
	lss esp, [stack_prt]

	; 设置8253计时器，把计时器通道0设置成每隔10ms向中断控制器发送一个中断请求信号
	mov al,	0x36
	mov edx, 0x43
	out dx,	al
	mov eax, 11930
	mov edx, 0x40
	mov edx, 0x40
	out dx, al
	mov al, ah
	out dx, al

	; int 0x01;
	; 到此停止
	jmp	$

SegCode32Len	equ	$ - SEG_CODE32

TIMER_INT:
	mov	ax, SelectorData32
	mov	ds, ax ;装载数据段

	mov	ax, SelectorVideo
	mov	gs, ax			; 视频段选择子(目的)
	mov	edi, (80 * 11 + 79) * 2	; 屏幕第 11 行, 第 79 列。
	mov	ah, 0Ch			; 0000: 黑底    1100: 红字
	mov	al, [word 0] 
	mov	[gs:edi], ax
TimerINTLen		equ	$ - TIMER_INT
